package com.zhuoyue.common.aop.auth;


import com.zhuoyue.common.exception.ErrorType;
import com.zhuoyue.common.exception.ZyServerException;
import com.zhuoyue.common.jwt.util.JwtOperator;
import io.jsonwebtoken.Claims;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.annotation.Order;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;

import static com.zhuoyue.common.constant.RequestType.*;

/**
 * @author wjming
 * @ClassName: AuthAspect
 * @Description: 用户登陆AOP, 通过account_orgCode方式获取redis中的token信息
 * @Date 2021-06-29 15:57
 */
@Aspect
@Component
@Order(1)
public class AuthAspect {
    @Autowired
    private JwtOperator jwtOperator;

    @Autowired
    private RedisTemplate redisTemplate;

    @Value("${spring.profiles.active}")
    private String active;
    private static final String BEARER = "Bearer ";

    @Around("@annotation(com.zhuoyue.common.aop.auth.CheckLogin)")
    public Object checkLogin(ProceedingJoinPoint point) throws Throwable {
        //if ("prod".equals(active)) {
        checkToken();
        //}
        return point.proceed();
    }

    private void checkToken() {
        HttpServletRequest request = getHttpServletRequest();
        String tokenStr = request.getHeader("Authorization");
        String orgCode = request.getHeader("organizationCode");

        //2.校验token是否合法&是否过期，如果不合法或已过期直接抛异常，:如果合法放行
        //validateToken用来校验token是否合法或过期
        try {
            String token = null;
            if (tokenStr.startsWith(BEARER)) {
                token = tokenStr.substring(7);
            }
            Boolean isValid = jwtOperator.validateToken(token);
            if (!isValid) {
                throw new SecurityException("token不合法");
            }

            //3.如果校验成功，就将用户的信息设置到request的attribute里面
            Claims claims = jwtOperator.getClaimsFromToken(token);
            //先从redis中获取一下token是否存在
            String redisToken = null;
            try {
                //如果type是第三方请求，则放行

                String type = claims.get("type") == null ? "" : claims.get("type").toString();
                switch (type) {
                    //目前所有语音设备的总称
                    case VOICE:
                        //小度
                    case DUEROS:
                        //若琪
                    case ROKID:
                        //天猫
                    case TMALL:
                        //后台管理系统
                    case MANAGE:
                        //微信小程序
                    case WXXCX:
                        break;
                    default:
                        Object tokenMessage = redisTemplate.opsForValue().get(claims.get("account"));
                        if (tokenMessage == null) {
                            redisToken = (String) redisTemplate.opsForValue().get(claims.get("account") + "_" + orgCode);
                        } else {
                            redisToken = tokenMessage.toString();
                        }

                        if (StringUtils.isEmpty(redisToken) || !token.equals(redisToken)) {
                            throw new SecurityException("token已失效");
                        }
                        String idStr = claims.get("id").toString();
                        User user = User.builder().id(idStr)
                                .account((String) claims.get("account"))
                                .orgCode(orgCode)
                                .sourceId((String) claims.get("sourceId"))
                                .sourceType((Integer) claims.get("sourceType")).build();
                        request.setAttribute("user", user);
                }

            } catch (Exception ex) {
                throw new ZyServerException(ErrorType.Redis_Can_Not_Connection);
            }
        } catch (Exception e) {
            throw new SecurityException("token已失效");
        }

    }

    private HttpServletRequest getHttpServletRequest() {
        //1.从header里面获取token
        RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
        ServletRequestAttributes attributes = (ServletRequestAttributes) requestAttributes;
        return attributes.getRequest();
    }

}
